package org.lqk.file.transfer.client.framework;

import io.netty.channel.ChannelHandlerContext;

import org.lqk.file.transfer.client.processor.FileSegmentResponseProcessor;
import org.lqk.file.transfer.client.processor.FileTaskResponseProcessor;
import org.lqk.file.transfer.netty.RequestFuture;
import org.lqk.file.transfer.protocol.CmdCode;
import org.lqk.file.transfer.protocol.RemotingCommand;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Created by Administrator on 2015/8/26.
 */
public class FileResponseProcessorDispatcher {
	private ConcurrentHashMap<Integer, RequestFuture> requestTable;
	private final HashMap<Integer,FileResponseProcessor> processorTable = new HashMap<Integer, FileResponseProcessor>();
	private final static Logger log = LoggerFactory.getLogger(FileResponseProcessorDispatcher.class);
	public FileResponseProcessorDispatcher(ConcurrentHashMap<Integer, RequestFuture> requestTable) {
		this.requestTable = requestTable;
		FileResponseProcessor fileTaskRequestProcessor = new FileTaskResponseProcessor(requestTable, CmdCode.File_Task.getCode());
		FileResponseProcessor fileSegmentRequestProcessor = new FileSegmentResponseProcessor(requestTable,CmdCode.File_Segment.getCode());
		processorTable.put(fileTaskRequestProcessor.getCmdCode(), fileTaskRequestProcessor);
		processorTable.put(fileSegmentRequestProcessor.getCmdCode(), fileSegmentRequestProcessor);
	}
	
	/**
	 * 处理请求消息
	 * 
	 * @param ctx
	 * @param command
	 */
	public void processCommand(final ChannelHandlerContext ctx, RemotingCommand command) {
		log.debug("request table size {}",requestTable.size());
		RequestFuture requestFuture = requestTable.get(command.getOpaque());
		/*
		 *  保存最后返回的结果，根据返回结果的类型和相关属性值，可以知道是否发送成功了。
		 *  做的更好些，为callback添加一个方法，就可以计算进度
		 */
		requestFuture.putResponse(command);
		final FileResponseProcessor processor = processorTable.get(command.getCmdCode());
//		if(requestFuture.isTimeout()){
//			requestFuture.executeCallBack();
//			//TODO 确认这句话的合适位置
//			requestTable.remove(command.getOpaque());
//			log.debug("timeout");
//		}
		
		if (requestFuture.getCallBack() != null) {
			Runnable runnable = () -> {
				try {
					boolean result = processor.process(ctx,command);
                    log.debug("processor {} process result {}",processor.getClass().getName(),result);
					// true，说明处理成功或失败，业务流程的netty部分已经结束，交给用户负责
//					boolean isEnd = result || requestFuture.isTimeout();
					boolean isEnd = result;
					if(isEnd){
						requestFuture.executeCallBack();
						//TODO 确认这句话的合适位置
						requestTable.remove(command.getOpaque());
					}
				} catch (Throwable e) {
					e.printStackTrace();
				}
			};
			ctx.executor().submit(runnable);
		}
		
	}
}
